(function($) {
	$.extend({
		tablesorterPager: new function() {
			
			function updatePageDisplay(c) {
				//var s = $(c.cssPageDisplay, c.container).val((c.page+1) + c.seperator + c.totalPages);

				var text = c.pageDisplayText;
				var pattern = /\{/g;

				do{
				    var matches = pattern.exec(text);

				    if (matches != null) {

				        var matches2 = /\}/.exec( matches.input.substring(matches.index, matches.input.length) );

				        var action = matches2.input.substring(0, matches2.index + 1);

				        switch(action){
				            case '{cr}':
				            	var x = (c.page + 1) * c.size;
				            	var r = ( x <= c.rowsCopy.length ) ? x : c.rowsCopy.length % c.size;
				                text = text.replace(action, r);
				                break;
				            case '{tr}':
				                text = text.replace(action, c.rowsCopy.length);
				                break;
				            case '{cp}':
				            	text = text.replace(action, c.page);
				            	break;
				            case '{tp}':
				            	text = text.replace(action, c.totalPages);
				            	break;
				        };
				    };

				} while (matches != null);

				// delete de brakets
				text = text.replace(/[\{\}]/g, '');

				$(c.cssPageDisplay, c.container).val(text);
			}
			
			function setPageSize(table, size) {
				var c = table.config;
				c.size = size;
				c.totalPages = Math.ceil(c.totalRows / c.size);
				c.pagerPositionSet = false;
				moveToPage(table);
				fixPosition(table);
			}
			
			function fixPosition(table) {
				var c = table.config;
				if(!c.pagerPositionSet && c.positionFixed) {
					var c = table.config, o = $(table);
					if(o.offset) {
						c.container.css({
							top: o.offset().top + o.height() + 'px',
							position: 'absolute'
						});
					}
					c.pagerPositionSet = true;
				}
			}
			
			function moveToFirstPage(table) {
				var c = table.config;
				c.page = 0;
				moveToPage(table);
			}
			
			function moveToLastPage(table) {
				var c = table.config;
				c.page = (c.totalPages-1);
				moveToPage(table);
			}
			
			function moveToNextPage(table) {
				var c = table.config;
				c.page++;
				if(c.page >= (c.totalPages-1)) {
					c.page = (c.totalPages-1);
				}
				moveToPage(table);
			}
			
			function moveToPrevPage(table) {
				var c = table.config;
				c.page--;
				if(c.page <= 0) {
					c.page = 0;
				}
				moveToPage(table);
			}
			
			function moveToPage(table) {
				var c = table.config;
				if(c.page < 0 || c.page > (c.totalPages-1)) {
					c.page = 0;
				}
				
				renderTable(table,c.rowsCopy);
			}
			
			function renderTable(table, rows) {
				
				var c = table.config;
				var l = rows.length;
				var s = (c.page * c.size);
				var e = (s + c.size);
				if(e > rows.length ) {
					e = rows.length;
				}
				
				var tableBody = $(table.tBodies[0]);
				
				// clear the table body
				$.tablesorter.clearTableBody(table);
				
				for(var i = s; i < e; i++) {
					
					//tableBody.append(rows[i]);
					var o = rows[i];
					var l = o.length;
					for(var j=0; j < l; j++) {
						tableBody[0].appendChild(o[j]);
					}
				}
				
				fixPosition(table, tableBody);
				
				$(table).trigger("applyWidgets");
				
				if( c.page >= c.totalPages ) {
        			moveToLastPage(table);
				}
				
				updatePageDisplay(c);

				//added
				renderControls(table);
				disableControls(c);
			}
			
			this.appender = function(table, rows) {
				
				var c = table.config;
				
				c.rowsCopy = rows;
				c.totalRows = rows.length;
				c.totalPages = Math.ceil(c.totalRows / c.size);
				
				renderTable(table, rows);
			};

			function renderControls (table) {
				var c = table.config;

				var $controlsContainer = $(c.cssUlContainer, c.container);
				$controlsContainer.children().remove();

				//generate pages number
				for (var i = 0; i < c.totalPages; i++) {
					var $li = $('<li/>');
					$li.appendTo($controlsContainer);

					var $a = $('<a href="#"/>')
					.addClass( c.pageNumberClass )
					.html( i+1 )
					.appendTo( $li )
					.click(function (){
						var content = $(this).html();
						if ( !isNaN(content) ) {
							c.page = content - 1;

							$( 'a.' + c.activeClass, $controlsContainer).removeClass();
							$(this).addClass( c.activeClass );

							moveToPage(table);

							disableControls(c);
						};
						return false;
					});
					if (c.page == i) {
						$a.addClass( c.activeClass );
					};
				};

				//generate relative controls if they are setted in the config options
				if(c.controls){
					var $li = $('<li/>');
					$li.prependTo($controlsContainer);

					var $a = $('<a href="#"/>')
					.addClass( c.prevClass )
					.html( c.htmlPrev )
					.appendTo( $li )
					.click(function (){
						moveToPrevPage(table);
						disableControls(c);
						return false;
					});

					var $li = $('<li/>');
					$li.appendTo($controlsContainer);

					$('<a href="#"/>')
					.addClass( c.nextClass )
					.html( c.htmlNext )
					.appendTo( $li )
					.click(function (){
						moveToNextPage(table);
						disableControls(c);
						return false;
					});
				};

				//generate absolute controls if requested
				if ( c.absoluteControls ) {
					var $li = $('<li/>');
					$li.prependTo($controlsContainer);

					var $a = $('<a href="#"/>')
					.addClass( c.firstClass )
					.html( c.htmlFirst )
					.appendTo( $li )
					.click(function (){
						moveToFirstPage(table);
						disableControls(c);
						return false;
					});

					var $li = $('<li/>');
					$li.appendTo($controlsContainer);

					$('<a href="#"/>')
					.addClass( c.lastClass )
					.html( c.htmlLast )
					.appendTo( $li )
					.click(function (){
						moveToLastPage(table);
						disableControls(c);
						return false;
					});
				};
			};

			function disableControls (config) {
				//TODO: incluir los controles absolutos
				var all = prev = next = false;
				if (config.page == 0 && config.totalPages == 1) {
					all = true;
				};
				if(config.page == (config.totalPages - 1) ){
					next = true;
				};
				if (config.page == 0) {
					prev = true;
				};

				var selector = "";
				selector = " ." + config.nextClass + ", ." + config.prevClass;
				if (all) {
					$(selector, config.cssUlContainer).addClass('disabled');
				}else{
					$(selector, config.cssUlContainer).removeClass('disabled');
				};
				if (prev){
					selector = " ." + config.prevClass;
					$(selector, config.cssUlContainer).addClass('disabled');
				}
				else{
					selector = " ." + config.nextClass;
					$(selector, config.cssUlContainer).addClass('disabled');
				};
			};
			
			this.defaults = {
				size: 10,
				offset: 0,
				page: 0,
				totalRows: 0,
				totalPages: 0,
				container: null,

				//updated (.next -> next)
				nextClass: 'next',
				prevClass: 'prev',
				firstClass: 'first',
				lastClass: 'last',
				activeClass: 'active',		// active class for the 'a' tag
				pageNumberClass: 'number',	// class for numbers in the pager

				cssPageDisplay: '.pagedisplay',
				seperator: "/",
				positionFixed: true,
				appender: this.appender,
				//added
				pageDisplayText: '{cp}/{tp}',// cp-> current Page, tp-> total Pages, cr-> current Rows, tr-> total Rows
				cssPageSize: '.pagesize',
				absoluteControls: false,	// true if you want first and last controls
				htmlFirst: '&lt;&lt;',		// html content for first control
				htmlLast: '&gt;&gt;',		// html content for last control
				controls: true,				// true if you want prev and next controls
				htmlPrev: '&lt;',			// html contrent for prev control
				htmlNext: '&gt;',			// html content for next control
				cssUlContainer: '.pagination'
			};
			
			this.construct = function(settings) {
				
				return this.each(function() {	
					
					config = $.extend(this.config, $.tablesorterPager.defaults, settings);
					var table = this, pager = config.container;
				
					$(this).trigger("appendCache");
					
					//Updated: put the 'config.cssPageSize' dynamic for customization
					var n = parseInt( $(config.cssPageSize, pager).val() );
					if (isNaN( n )) {
						n = config.size;
					};
					setPageSize( table, n );
					
					$(config.cssPageSize, pager).change(function() {
						setPageSize( table, parseInt($(this).val()) );
						return false;
					});
				});
			};
			
		}
	});
	// extend plugin scope
	$.fn.extend({
        tablesorterPager: $.tablesorterPager.construct
	});
	
})(jQuery);				